import * as THREE from "three"

let createYellowSandwich = () => {
    // 1. geometry
    let geometry = new THREE.Geometry()
    let verticesXY = vertices(FiveStar.R * 1.2)
    for (let i = 0; i < verticesXY.length; i++) {
        geometry.vertices.push(new THREE.Vector3(verticesXY[i].x, verticesXY[i].y, 0))
    }
    geometry.vertices.push(new THREE.Vector3(0, 0, 0))
    geometry.faces.push(new THREE.Face3(10, 5, 0))
    geometry.faces.push(new THREE.Face3(0, 9, 10))
    for (let i = 1; i < 5; i++) {
        geometry.faces.push(new THREE.Face3(i, i + 4, 10))
        geometry.faces.push(new THREE.Face3(10, i + 5, i))
    }

    // 2. material
    let material = new THREE.MeshBasicMaterial({
        color: 0xE7DD56,
        side: THREE.DoubleSide
    });

    // 3. mesh
    return new THREE.Mesh(geometry, material)
}
let create3dFiveStar = () => {
    // 1. geometry
    let geometry = new THREE.Geometry()
    let verticesXY = vertices(FiveStar.R)
    for (let i = 0; i < verticesXY.length; i++) {
        geometry.vertices.push(new THREE.Vector3(verticesXY[i].x, verticesXY[i].y, 0))
    }
    geometry.vertices.push(new THREE.Vector3(0, 0, 300))
    geometry.vertices.push(new THREE.Vector3(0, 0, -300))

    geometry.faces.push(new THREE.Face3(10, 5, 0))
    geometry.faces.push(new THREE.Face3(0, 9, 10))
    geometry.faces.push(new THREE.Face3(0, 5, 11))
    geometry.faces.push(new THREE.Face3(11, 9, 0))
    for (let i = 1; i < 5; i++) {
        geometry.faces.push(new THREE.Face3(i, i + 4, 10))
        geometry.faces.push(new THREE.Face3(10, i + 5, i))
        geometry.faces.push(new THREE.Face3(11, i + 4, i))
        geometry.faces.push(new THREE.Face3(i, i + 5, 11))
    }
    geometry.computeFlatVertexNormals()

    // 2. material
    let material = new THREE.MeshLambertMaterial({
        color: 0xE12432
    });

    // 3. mesh
    return new THREE.Mesh(geometry, material)
}
let vertices = (R) => {
    let points = [];
    const sin = (num) => Math.sin(num * Math.PI / 180)
    const cos = (num) => Math.cos(num * Math.PI / 180)
    /*
     * outer point
     */
    // top
    points.push({x: 0, y: R})
    // right top
    points.push({x: R * cos(18), y: R * sin(18)})
    // right bottom
    points.push({x: R * cos(54), y: 0 - R * sin(54)})
    // left bottom
    points.push({x: 0 - R * cos(54), y: 0 - R * sin(54)})
    // left top
    points.push({x: 0 - R * cos(18), y: R * sin(18)})

    /*
     * inner point
     */
    // inner radius
    let _r = R * sin(18) / sin(54)
    // right top
    points.push({x: _r * cos(54), y: _r * sin(54)})
    // right bottom
    points.push({x: _r * cos(18), y: 0 - _r * sin(18)})
    // bottom
    points.push({x: 0, y: 0 - _r})
    // left bottom
    points.push({x: 0 - _r * cos(18), y: 0 - _r * sin(18)})
    // left top
    points.push({x: 0 - _r * cos(54), y: _r * sin(54)})

    return points
}
/*
 * 1.2 create the lights
 */
let createLights = (scene) => {
    let point = new THREE.PointLight(0xFF2937);
    point.position.set(FiveStar.R * 1.5, FiveStar.R * 1.5, FiveStar.R * 1.5);
    scene.add(point);
    point = new THREE.PointLight(0x661016);
    point.position.set(-FiveStar.R * 1.5, -FiveStar.R * 1.5, FiveStar.R * 1.5);
    scene.add(point);
    let light = new THREE.DirectionalLight(0xFFFFFF, 2.5);
    light.position.set(-FiveStar.R, -FiveStar.R, -FiveStar.R);
    scene.add(light);
}

/*
 * 2. make the camera
 */
let createCamera = () => {
    // 2.1 create and chose type of OrthographicCamera (not PerspectiveCamera)
    let width = FiveStar.R * 2, height = FiveStar.R * 2
    let scale = width / height, ctrl = FiveStar.R * 2
    let near = 1, far = FiveStar.R * 3
    let camera = new THREE.OrthographicCamera(-ctrl * scale, ctrl * scale, ctrl, -ctrl, near, far);
    // 2.2 position
    camera.position.set(0, 0, FiveStar.R * 1.5)
    // 2.3 look-at
    camera.lookAt(0, 0, 0)
    return camera
}

/*
 * 3. make it renderer
 */
let renderer = (dom, scene, camera, mesh1, mesh2) => {
    // 3.1 renderer
    let renderer = new THREE.WebGLRenderer({alpha: true})
    renderer.setSize(FiveStar.R / 2, FiveStar.R / 2)
    // 3.2 binding
    dom.appendChild(renderer.domElement)

    // 3.3 render
    function render() {
        renderer.render(scene, camera)
        mesh1.rotateY(0.01)
        mesh2.rotateY(0.01)
        requestAnimationFrame(render)
    }

    render()
}

const FiveStar = (dom, R) => {
    FiveStar.R = R
    let scene = new THREE.Scene()

    let mesh3dFiveStar = create3dFiveStar();
    scene.add(mesh3dFiveStar)

    let meshYellowSandwich = createYellowSandwich()
    scene.add(meshYellowSandwich)

    createLights(scene)

    let camera = createCamera()
    renderer(dom, scene, camera, mesh3dFiveStar, meshYellowSandwich)
}

export default FiveStar
